/***************************************************
> Copyright (C) 2024 ==LX== All rights reserved.
> File Name: UserServer.c
> Author: lx
> Mail:2998218073@qq.com 
> Created Time: 2024年12月04日 星期三 14时10分33秒
***************************************************/
#include "UserServer.h"

int main(int argc, const char* argv[])
{
	db_init();  //数据连接成功的判断
	signal(SIGINT, handle_signal);
	//创建套接字,监听套接字
	server_socket = socket(AF_INET, SOCK_STREAM, 0);

	if (argc != 3)
	{
		printf("cmd ip port\n");
		return -1;
	}
	//bind 本机ip port
	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(atoi(argv[2]));   //port 
	saddr.sin_addr.s_addr = inet_addr(argv[1]);   //ip

	int optval = 1;
	//bind 的地址允许重复使用
	setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
	int isbind = bind(server_socket, (struct sockaddr*)&saddr, sizeof(saddr));
	if (isbind == -1)
	{
		perror("bind");
		return -1;
	}

	//启动监听
	int islisten = listen(server_socket, 10);
	if (islisten == -1)
	{
		perror("listen");
		return -1;
	}
	printf("监听已启动\n");

	int epfd = epoll_create(1);
	struct epoll_event ev;
	ev.events = EPOLLIN;
	ev.data.fd = server_socket;

	int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, server_socket, &ev);
	if (ret == -1)
	{
		perror("epoll_ctl");
		return -1;
	}
	struct sockaddr_in caddr;
	int addrlen = sizeof(caddr);
	char buf[6] = { 0 };
	struct epoll_event events[40];
	while (1)
	{
		int num = epoll_wait(epfd, events, 40, 20000);
		if (num == 0)
		{
			printf("num :%d\n", num);
			break;
		}
		for (int i = 0; i < num; i++)
		{
			int fd = events[i].data.fd;
			if (fd == server_socket)
			{
				int client_socket = accept(server_socket, (struct sockaddr*)&caddr, &addrlen);
				printf("ip:%s,port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
				ev.events = EPOLLIN | EPOLLET;
				ev.data.fd = client_socket;
				epoll_ctl(epfd, EPOLL_CTL_ADD, client_socket, &ev);
			}
			//创建子线程,读取数据
			ClientType ct;
			ct.epfd = epfd;
			ct.fd = fd;
			pthread_t tid;
			pthread_create(&tid, NULL, read_msg, (void*)&ct);
			pthread_detach(tid);
		}
	}
	close(server_socket);

	return 0;
}

void handle_signal(int signum)
{
	if (signum == SIGINT)
	{
		isrun = 0;
		close(server_socket);
		exit(0);
	}
}

void parseJson(const char* p, void* arg)
{
	Use s;
	cJSON* root = cJSON_Parse(p);
	if (root == NULL)
	{
		printf("JSON解析失败，请检查输入的JSON数据格式是否正确\n");
		return;
	}

	cJSON* order = cJSON_GetObjectItem(root, "order");
	cJSON* name = cJSON_GetObjectItem(root, "name");
	cJSON* passwd = cJSON_GetObjectItem(root, "pwd");

	strncpy(s.order, cJSON_GetStringValue(order), sizeof(s.order) - 1);
	s.order[sizeof(s.order) - 1] = '\0';  // 确保字符串以'\0'结尾
	strncpy(s.name, cJSON_GetStringValue(name), sizeof(s.name) - 1);
	s.name[sizeof(s.name) - 1] = '\0';
	strncpy(s.pwd, cJSON_GetStringValue(passwd), sizeof(s.pwd) - 1);
	s.pwd[sizeof(s.pwd) - 1] = '\0';

	printf("or:%s,na:%s,pwd:%s\n", s.order, s.name, s.pwd);

	if (strcmp(s.order, "login") == 0)
	{
		int temp = query_data(s);
		if (temp == 1)
		{
			send_response(((ClientType*)arg)->fd, "登录成功");
		}
		else
		{
			send_response(((ClientType*)arg)->fd, "登录失败");
		}
	}
	if (strcmp(s.order, "register") == 0)
	{
		//先检查用户名是否已存在
		int exists = check_username_exists(s.name);
		if (exists == 1)
		{
			send_response(((ClientType*)arg)->fd, "用户名已存在，注册失败");
			return;
		}

		int flag = insert_data(s);
		if (flag == -1)
		{
			send_response(((ClientType*)arg)->fd, "注册失败");
			printf("入库失败\n");
		}
		else if (flag == 0)
		{
			send_response(((ClientType*)arg)->fd, "注册成功");
			printf("入库成功\n");
		}
	}
	/*
	if (strcmp(s.order, "modify") == 0)
	{
		int val =
		if (val == 1)
		{
			int result = update_password(s);
			if (result == 0)
			{
				printf("密码修改成功\n");
				send_response(((ClientType*)arg)->fd, "update_password_success");
			}
			else
			{
				printf("密码修改失败\n");
				send_response(((ClientType*)arg)->fd, "update_password_failed");
			}
		}
		else
		{
			printf("用户名或旧密码错误，密码修改失败\n");
			send_response(((ClientType*)arg)->fd, "update_password_failed_invalid_user_pwd");
		}
	}
	*/
}

void* read_msg(void* arg)
{
	ClientType ct = *(ClientType*)arg;
	char buf[1024] = { 0 };
	struct epoll_event ev;
	ev.events = EPOLLIN | EPOLLET;
	ev.data.fd = ct.fd;
	while (1)
	{
		memset(buf, 0, sizeof(buf));
		int size = read(ct.fd, buf, 1023);

		if (size == -1)
		{
			if (errno == EAGAIN || errno == EWOULDBLOCK)
			{
				continue;  // 暂时无数据可读，继续等待下次读取
			}
			else
			{
				// 其他错误，关闭连接，移除epoll事件等操作
				epoll_ctl(ct.epfd, EPOLL_CTL_DEL, ct.fd, &ev);
				close(ct.fd);
				return 0;
			}
		}
		//断开连接
		if (size == 0)
		{
			epoll_ctl(ct.epfd, EPOLL_CTL_DEL, ct.fd, &ev);
			close(ct.fd);
		}
		if (size > 0)
		{
			printf("buf:%s\n", buf);
			//解包
			parseJson(buf, &ct);
		}
	}

}

int insert_data(Use use)
{
	char buf[1024] = { 0 };
	sprintf(buf, "insert into accountinfo (username,passwd) values ('%s','%s')", use.name, use.pwd);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		printf("数据入库失败:%s\n", mysql_error(mysql));
		return -1;
	}
	return 0;
}
int query_data(Use use)
{
	MYSQL_RES* res = NULL;
	MYSQL_ROW row;
	MYSQL_FIELD* field = NULL;
	int i = 0;
	int j = 0;
	char buf[1024] = { 0 };

	sprintf(buf, "select username,passwd from accountinfo");
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		printf("%s\n", mysql_error(mysql));
		return -1;
	}

	//显示查询结果
	//获得结果集
	res = mysql_store_result(mysql);
	//结果集的字段信息
	field = mysql_fetch_fields(res);
	//遍历行/记录 
	my_ulonglong Row = mysql_num_rows(res);
	if (Row < 1)
	{
		return -1;
	}
	//遍历列/字段个数
	int col = mysql_num_fields(res);
	for (i = 0; i < Row; i++)
	{
		row = mysql_fetch_row(res);
		//比较row[0]  --name   row[1] -- passwd 
		if (strcmp(use.name, row[0]) == 0 && strcmp(use.pwd, row[1]) == 0)
		{
			return 1;
		}
	}
	return 0;
}
// 发送消息给客户端
void send_response(int client_fd, const char* message)
{
	int len = strlen(message);
	int sent_bytes = 0;
	while (sent_bytes < len)
	{
		int ret = write(client_fd, message + sent_bytes, len - sent_bytes);
		if (ret == -1)
		{
			if (errno == EAGAIN || errno == EWOULDBLOCK)
			{
				// 遇到缓冲区满等情况，稍作等待后再尝试发送
				usleep(1000);
				continue;
			}
			else
			{
				// 发送出现其他严重错误，关闭连接
				close(client_fd);
				return;
			}
		}
		sent_bytes += ret;
	}
}
int check_user_exists(const char* username)
{
	MYSQL_RES* res = NULL;
	MYSQL_ROW row;
	char buf[1024] = { 0 };
	sprintf(buf, "select username,passwd from accountinfo where username = '%s' and passwd = '%s'", username, password);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		printf("%s\n", mysql_error(mysql));
		return -1;
	}

	res = mysql_store_result(mysql);
	if (res == NULL)
	{
		return 0;
	}

	if (mysql_num_rows(res) > 0)
	{
		return 1;
	}
	return 0;
}

// 修改密码
int update_password(Use use)
{
	char buf[1024] = { 0 };
	sprintf(buf, "update accountinfo set passwd = '%s' where username = '%s'", use.new_pwd, use.name);
	int ret = mysql_real_query(mysql, buf, strlen(buf));
	if (ret != 0)
	{
		printf("密码更新失败:%s\n", mysql_error(mysql));
		return -1;
	}
	return 0;
}

int db_init()
{
	//初始化mysql句柄
	mysql = mysql_init(NULL);
	if (mysql == NULL)
	{
		perror("mysql_init");
		return -1;
	}

	//连接数据库
	MYSQL* conn = mysql_real_connect(mysql, "localhost", "root", "123456", "db_lanxiao", 0, NULL, 0);
	if (conn == NULL)
	{
		perror("mysql_real_connect");
		return -1;
	}
	return 0;
}
